using MicroMsg.Common.Pointer;
using System;
namespace MicroMsg.Common.Algorithm
{
	public class BigNum
	{
		public const int XYSSL_ERR_MPI_FILE_IO_ERROR = -2;
		public const int XYSSL_ERR_MPI_BAD_INPUT_DATA = -4;
		public const int XYSSL_ERR_MPI_INVALID_CHARACTER = -6;
		public const int XYSSL_ERR_MPI_BUFFER_TOO_SMALL = -8;
		public const int XYSSL_ERR_MPI_NEGATIVE_VALUE = -10;
		public const int XYSSL_ERR_MPI_DIVISION_BY_ZERO = -12;
		public const int XYSSL_ERR_MPI_NOT_ACCEPTABLE = -14;
		public const int ciL_INT8 = 1;
		public const int ciL_INT16 = 2;
		public const int ciL_INT32 = 4;
		public static readonly int ciL = 4;
		public static readonly int biL = BigNum.ciL << 3;
		public static readonly int biH = BigNum.ciL << 2;
		internal static readonly int[] smallPrime = new int[]
		{
			3,
			5,
			7,
			11,
			13,
			17,
			19,
			23,
			29,
			31,
			37,
			41,
			43,
			47,
			53,
			59,
			61,
			67,
			71,
			73,
			79,
			83,
			89,
			97,
			101,
			103,
			107,
			109,
			113,
			127,
			131,
			137,
			139,
			149,
			151,
			157,
			163,
			167,
			173,
			179,
			181,
			191,
			193,
			197,
			199,
			211,
			223,
			227,
			229,
			233,
			239,
			241,
			251,
			257,
			263,
			269,
			271,
			277,
			281,
			283,
			293,
			307,
			311,
			313,
			317,
			331,
			337,
			347,
			349,
			353,
			359,
			367,
			373,
			379,
			383,
			389,
			397,
			401,
			409,
			419,
			421,
			431,
			433,
			439,
			443,
			449,
			457,
			461,
			463,
			467,
			479,
			487,
			491,
			499,
			503,
			509,
			521,
			523,
			541,
			547,
			557,
			563,
			569,
			571,
			577,
			587,
			593,
			599,
			601,
			607,
			613,
			617,
			619,
			631,
			641,
			643,
			647,
			653,
			659,
			661,
			673,
			677,
			683,
			691,
			701,
			709,
			719,
			727,
			733,
			739,
			743,
			751,
			757,
			761,
			769,
			773,
			787,
			797,
			809,
			811,
			821,
			823,
			827,
			829,
			839,
			853,
			857,
			859,
			863,
			877,
			881,
			883,
			887,
			907,
			911,
			919,
			929,
			937,
			941,
			947,
			953,
			967,
			971,
			977,
			983,
			991,
			997,
			-103
		};
		public static int bitsToLimbs(int int_0)
		{
			return (int_0 + BigNum.biL - 1) / BigNum.biL;
		}
		public static int charsToLimbs(int int_0)
		{
			return (int_0 + BigNum.ciL - 1) / BigNum.ciL;
		}
		public static void mpiInit(MPI mpi_0)
		{
			mpi_0.int_0 = 1;
			mpi_0.int_1 = 0;
			mpi_0.plongArray_0.value_ = null;
		}
		public static int mpiGrow(MPI mpi_0, int nblimbs)
		{
			if (mpi_0.int_1 < nblimbs)
			{
				long[] array = new long[nblimbs];
				if (array == null)
				{
					return 1;
				}
				Arrays.fill(array, 0);
				if (mpi_0.int_1 > 0)
				{
					Array.Copy(mpi_0.plongArray_0.value_, 0, array, 0, mpi_0.int_1);
				}
				mpi_0.plongArray_0.value_ = array;
				mpi_0.int_1 = nblimbs;
			}
			return 0;
		}
		public static int mpiCopy(MPI mpi_0, MPI mpi_1)
		{
			if (mpi_0 == mpi_1)
			{
				return 0;
			}
			int num = mpi_1.int_1 - 1;
			while (num > 0 && mpi_1.plongArray_0.value_[num] == 0L)
			{
				num--;
			}
			num++;
			mpi_0.int_0 = mpi_1.int_0;
			int num2 = BigNum.mpiGrow(mpi_0, num);
			if (num2 != 0)
			{
				return num2;
			}
			Arrays.fill(mpi_0.plongArray_0.value_, 0);
			Array.Copy(mpi_1.plongArray_0.value_, 0, mpi_0.plongArray_0.value_, 0, num);
			return 0;
		}
		public static void mpiSwap(MPI mpi_0, MPI mpi_1)
		{
			MPI mPI = new MPI();
			BigNum.mpiCopy(mPI, mpi_0);
			BigNum.mpiCopy(mpi_0, mpi_1);
			BigNum.mpiCopy(mpi_1, mPI);
		}
		public static int mpiLset(MPI mpi_0, int int_0)
		{
			int num = BigNum.mpiGrow(mpi_0, 1);
			if (num != 0)
			{
				return num;
			}
			Arrays.fill(mpi_0.plongArray_0.value_, 0);
			if (int_0 < 0)
			{
				mpi_0.plongArray_0.value_[0] = (long)(-(long)int_0);
			}
			else
			{
				mpi_0.plongArray_0.value_[0] = (long)int_0;
			}
			if (int_0 < 0)
			{
				mpi_0.int_0 = -1;
			}
			else
			{
				mpi_0.int_0 = 1;
			}
			return 0;
		}
		public static int mpiLsb(MPI mpi_0)
		{
			int num = 0;
			for (int i = 0; i < mpi_0.int_1; i++)
			{
				int j = 0;
				while (j < BigNum.biL)
				{
					if ((mpi_0.plongArray_0.value_[i] >> j & 1L) != 0L)
					{
						return num;
					}
					j++;
					num++;
				}
			}
			return 0;
		}
		public static int mpiMsb(MPI mpi_0)
		{
			int num = mpi_0.int_1 - 1;
			while (num > 0 && mpi_0.plongArray_0.value_[num] == 0L)
			{
				num--;
			}
			int num2 = BigNum.biL - 1;
			while (num2 >= 0 && (mpi_0.plongArray_0.value_[num] >> num2 & 1L) == 0L)
			{
				num2--;
			}
			return num * BigNum.biL + num2 + 1;
		}
		public static int mpiSize(MPI mpi_0)
		{
			return BigNum.mpiMsb(mpi_0) + 7 >> 3;
		}
		public static int mpiGetDigit(PInt pI, int radix, byte byte_0)
		{
			pI.value_ = 255;
			if (byte_0 >= 48 && byte_0 <= 57)
			{
				pI.value_ = (int)(byte_0 - 48);
			}
			if (byte_0 >= 65 && byte_0 <= 70)
			{
				pI.value_ = (int)(byte_0 - 55);
			}
			if (byte_0 >= 97 && byte_0 <= 102)
			{
				pI.value_ = (int)(byte_0 - 87);
			}
			if (pI.value_ >= radix)
			{
				return -6;
			}
			return 0;
		}
		public static int mpiReadString(MPI mpi_0, int radix, string string_0)
		{
			byte[] array = SupportClass.ToByteArray(string_0);
			if (radix >= 2 && radix <= 16)
			{
				MPI mPI = new MPI();
				BigNum.mpiInit(mPI);
				if (radix == 16)
				{
					int nblimbs = BigNum.bitsToLimbs(array.Length << 2);
					int num = BigNum.mpiGrow(mpi_0, nblimbs);
					if (num != 0)
					{
						return num;
					}
					num = BigNum.mpiLset(mpi_0, 0);
					if (num != 0)
					{
						return num;
					}
					PInt pInt = new PInt();
					int i = array.Length - 1;
					int num2 = 0;
					while (i >= 0)
					{
						if (i == 0 && array[i] == 45)
						{
							mpi_0.int_0 = -1;
							break;
						}
						num = BigNum.mpiGetDigit(pInt, radix, array[i]);
						if (num != 0)
						{
							return num;
						}
						mpi_0.plongArray_0.value_[num2 / (2 * BigNum.ciL)] |= (long)pInt.value_ << (num2 % (2 * BigNum.ciL) << 2);
						i--;
						num2++;
					}
				}
				else
				{
					int num = BigNum.mpiLset(mpi_0, 0);
					PInt pInt2 = new PInt();
					for (int i = 0; i < array.Length; i++)
					{
						if (i == 0 && array[i] == 45)
						{
							mpi_0.int_0 = -1;
						}
						else
						{
							num = BigNum.mpiGetDigit(pInt2, radix, array[i]);
							if (num != 0)
							{
								return num;
							}
							num = BigNum.mpiMulInt(mPI, mpi_0, (long)radix);
							if (num != 0)
							{
								return num;
							}
							num = BigNum.mpiAddInt(mpi_0, mPI, pInt2.value_);
							if (num != 0)
							{
								return num;
							}
						}
					}
				}
				return 0;
			}
			return -4;
		}
		public static int mpiWriteHlp(MPI mpi_0, int radix, PByteArray pbyteArray_0, PInt pIdx)
		{
			PLong pLong = new PLong();
			if (radix < 2 || radix > 16)
			{
				return -4;
			}
			int num = BigNum.mpiModInt(pLong, mpi_0, radix);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiDivInt(mpi_0, null, mpi_0, radix);
			if (num != 0)
			{
				return num;
			}
			if (BigNum.mpiCmpInt(mpi_0, 0) != 0)
			{
				num = BigNum.mpiWriteHlp(mpi_0, radix, pbyteArray_0, pIdx);
				if (num != 0)
				{
					return num;
				}
			}
			long value_ = pLong.value_;
			if (value_ < 10L)
			{
				pbyteArray_0.value_[pIdx.value_++] = (byte)(value_ + 48L);
			}
			else
			{
				pbyteArray_0.value_[pIdx.value_++] = (byte)(value_ + 55L);
			}
			return 0;
		}
		public static int mpiWriteString(MPI mpi_0, int radix, PByteArray pbyteArray_0)
		{
			MPI mpi_ = new MPI();
			BigNum.mpiInit(mpi_);
			if (radix >= 2 && radix <= 16)
			{
				int num = BigNum.mpiMsb(mpi_0);
				if (radix >= 4)
				{
					num >>= 1;
				}
				if (radix >= 16)
				{
					num >>= 1;
				}
				num += 3;
				byte[] array = new byte[4 * (num + 1)];
				Arrays.fill(array, 0);
				int num2 = 0;
				if (mpi_0.int_0 == -1)
				{
					array[num2++] = 45;
				}
				if (radix == 16)
				{
					int i = mpi_0.int_1 - 1;
					int num3 = 0;
					while (i >= 0)
					{
						for (int j = BigNum.ciL - 1; j >= 0; j--)
						{
							int num4 = (int)(mpi_0.plongArray_0.value_[i] >> (j << 3)) & 255;
							if (num4 != 0 || num3 != 0 || i + j == 0)
							{
								array[num2++] = (byte)(num4 / 16);
								array[num2++] = (byte)(num4 % 16);
								num3 = 1;
							}
						}
						i--;
					}
				}
				else
				{
					int num5 = BigNum.mpiCopy(mpi_, mpi_0);
					if (num5 != 0)
					{
						return num5;
					}
					PInt pInt = new PInt();
					pInt.value_ = num2;
					PByteArray pByteArray = new PByteArray();
					pByteArray.value_ = new byte[4 * (num + 1)];
					Arrays.fill(pByteArray.value_, 0);
					for (int k = 0; k < num2; k++)
					{
						pByteArray.value_[k] = array[k];
					}
					num5 = BigNum.mpiWriteHlp(mpi_, radix, pByteArray, pInt);
					if (num5 != 0)
					{
						return num5;
					}
				}
				pbyteArray_0.value_ = new byte[num2];
				Array.Copy(array, 0, pbyteArray_0.value_, 0, num2);
				return 0;
			}
			return -4;
		}
		public static int mpiReadBinary(MPI mpi_0, PByteArray pbyteArray_0)
		{
			int num = 0;
			while (num < pbyteArray_0.value_.GetLength(0) && pbyteArray_0.value_[num] == 0)
			{
				num++;
			}
			int num2 = BigNum.mpiGrow(mpi_0, BigNum.charsToLimbs(pbyteArray_0.value_.GetLength(0) - num));
			if (num2 != 0)
			{
				return num2;
			}
			num2 = BigNum.mpiLset(mpi_0, 0);
			if (num2 != 0)
			{
				return num2;
			}
			int i = pbyteArray_0.value_.GetLength(0) - 1;
			int num3 = 0;
			while (i >= num)
			{
				mpi_0.plongArray_0.value_[num3 / BigNum.ciL] |= (long)(pbyteArray_0.value_[i] & 255) << (num3 % BigNum.ciL << 3);
				i--;
				num3++;
			}
			return 0;
		}
		public static int mpiWriteBinary(MPI mpi_0, PByteArray pbyteArray_0)
		{
			int i = BigNum.mpiSize(mpi_0);
			if (pbyteArray_0.value_.Length < i)
			{
				return -8;
			}
			Arrays.fill(pbyteArray_0.value_, 0);
			int num = i - 1;
			int num2 = 0;
			while (i > 0)
			{
				pbyteArray_0.value_[num] = (byte)(mpi_0.plongArray_0.value_[num2 / BigNum.ciL] >> (num2 % BigNum.ciL << 3));
				num--;
				num2++;
				i--;
			}
			return 0;
		}
		public static int mpiShiftL(MPI mpi_0, int count)
		{
			long num = 0L;
			int num2 = count / BigNum.biL;
			int num3 = count & BigNum.biL - 1;
			int i = BigNum.mpiMsb(mpi_0) + count;
			if (mpi_0.int_1 * BigNum.biL < i)
			{
				int num4 = BigNum.mpiGrow(mpi_0, BigNum.bitsToLimbs(i));
				if (num4 != 0)
				{
					return num4;
				}
			}
			if (num2 > 0)
			{
				for (i = mpi_0.int_1 - 1; i >= num2; i--)
				{
					mpi_0.plongArray_0.value_[i] = mpi_0.plongArray_0.value_[i - num2];
				}
				while (i >= 0)
				{
					mpi_0.plongArray_0.value_[i] = 0L;
					i--;
				}
			}
			if (num3 > 0)
			{
				for (i = num2; i < mpi_0.int_1; i++)
				{
					long num5 = mpi_0.plongArray_0.value_[i] >> BigNum.biL - num3;
					mpi_0.plongArray_0.value_[i] <<= num3;
					BigNum.overflowAndModify(mpi_0, i);
					mpi_0.plongArray_0.value_[i] |= num;
					BigNum.overflowAndModify(mpi_0, i);
					num = num5;
				}
			}
			return 0;
		}
		public static int mpiShiftR(MPI mpi_0, int count)
		{
			long num = 0L;
			int num2 = count / BigNum.biL;
			int num3 = count & BigNum.biL - 1;
			if (num2 > 0)
			{
				int i;
				for (i = 0; i < mpi_0.int_1 - num2; i++)
				{
					mpi_0.plongArray_0.value_[i] = mpi_0.plongArray_0.value_[i + num2];
				}
				while (i < mpi_0.int_1)
				{
					mpi_0.plongArray_0.value_[i] = 0L;
					i++;
				}
			}
			if (num3 > 0)
			{
				for (int i = mpi_0.int_1 - 1; i >= 0; i--)
				{
					long num4 = mpi_0.plongArray_0.value_[i] << BigNum.biL - num3;
					BigNum.overflowAndModify(mpi_0, i);
					mpi_0.plongArray_0.value_[i] >>= num3;
					mpi_0.plongArray_0.value_[i] |= num;
					BigNum.overflowAndModify(mpi_0, i);
					num = num4;
				}
			}
			return 0;
		}
		public static int mpiCmpAbs(MPI mpi_0, MPI mpi_1)
		{
			int i = mpi_0.int_1 - 1;
			while (i >= 0 && mpi_0.plongArray_0.value_[i] == 0L)
			{
				i--;
			}
			int num = mpi_1.int_1 - 1;
			while (num >= 0 && mpi_1.plongArray_0.value_[num] == 0L)
			{
				num--;
			}
			if (i < 0 && num < 0)
			{
				return 0;
			}
			if (i > num)
			{
				return 1;
			}
			if (num > i)
			{
				return -1;
			}
			while (i >= 0)
			{
				if (mpi_0.plongArray_0.value_[i] > mpi_1.plongArray_0.value_[i])
				{
					return 1;
				}
				if (mpi_0.plongArray_0.value_[i] < mpi_1.plongArray_0.value_[i])
				{
					return -1;
				}
				i--;
			}
			return 0;
		}
		public static int mpiCmpMpi(MPI mpi_0, MPI mpi_1)
		{
			int i = mpi_0.int_1 - 1;
			while (i >= 0 && mpi_0.plongArray_0.value_[i] == 0L)
			{
				i--;
			}
			int num = mpi_1.int_1 - 1;
			while (num >= 0 && mpi_1.plongArray_0.value_[num] == 0L)
			{
				num--;
			}
			if (i < 0 && num < 0)
			{
				return 0;
			}
			if (i > num)
			{
				return mpi_0.int_0;
			}
			if (num > i)
			{
				return -mpi_0.int_0;
			}
			if (mpi_0.int_0 > 0 && mpi_1.int_0 < 0)
			{
				return 1;
			}
			if (mpi_1.int_0 > 0 && mpi_1.int_0 < 0)
			{
				return -1;
			}
			while (i >= 0)
			{
				if (mpi_0.plongArray_0.value_[i] > mpi_1.plongArray_0.value_[i])
				{
					return mpi_0.int_0;
				}
				if (mpi_0.plongArray_0.value_[i] < mpi_1.plongArray_0.value_[i])
				{
					return -mpi_0.int_0;
				}
				i--;
			}
			return 0;
		}
		public static int mpiCmpInt(MPI mpi_0, int int_0)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			mPI.plongArray_0.value_ = new long[1];
			if (int_0 < 0)
			{
				mPI.plongArray_0.value_[0] = (long)(-(long)int_0);
				mPI.int_0 = -1;
			}
			else
			{
				mPI.plongArray_0.value_[0] = (long)int_0;
				mPI.int_0 = 1;
			}
			mPI.int_1 = 1;
			return BigNum.mpiCmpMpi(mpi_0, mPI);
		}
		public static int overflowAndModify(MPI mpi_0, int int_0)
		{
			long num = mpi_0.plongArray_0.value_[int_0];
			int result = 0;
			if (num >> BigNum.biL != 0L)
			{
				result = (int)num >> BigNum.biL;
				byte[] array = TypeTransform.longToByteArrayHL(num);
				for (int i = 0; i < 8 - BigNum.ciL; i++)
				{
					array[i] = 0;
				}
				mpi_0.plongArray_0.value_[int_0] = TypeTransform.byteArrayHLToLong(array);
			}
			return result;
		}
		public static int mpiAddAbs(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			if (mpi_0 == mpi_2)
			{
				BigNum.mpiSwap(mpi_1, mpi_2);
			}
			int num;
			if (mpi_0 != mpi_1)
			{
				num = BigNum.mpiCopy(mpi_0, mpi_1);
				if (num != 0)
				{
					return num;
				}
			}
			int num2 = mpi_2.int_1 - 1;
			while (num2 >= 0 && mpi_2.plongArray_0.value_[num2] == 0L)
			{
				num2--;
			}
			num = BigNum.mpiGrow(mpi_0, num2 + 1);
			if (num != 0)
			{
				return num;
			}
			long num3 = 0L;
			int i;
			for (i = 0; i <= num2; i++)
			{
				mpi_0.plongArray_0.value_[i] += num3;
				num3 = (long)BigNum.overflowAndModify(mpi_0, i);
				mpi_0.plongArray_0.value_[i] += mpi_2.plongArray_0.value_[i];
				num3 += (long)BigNum.overflowAndModify(mpi_0, i);
			}
			while (num3 != 0L)
			{
				if (i >= mpi_0.int_1)
				{
					num = BigNum.mpiGrow(mpi_0, i + 1);
					if (num != 0)
					{
						return num;
					}
				}
				mpi_0.plongArray_0.value_[i] += num3;
				num3 = (long)BigNum.overflowAndModify(mpi_0, i);
				i++;
			}
			return 0;
		}
		public static int lessThan(long long_0, long long_1)
		{
			if (long_0 < long_1)
			{
				return 1;
			}
			return 0;
		}
		public static void mpiSubHlp(int int_0, MPI mpi_0, MPI mpi_1)
		{
			long num = 1L << (BigNum.biL & 31);
			int i = 0;
			long num2 = 0L;
			while (i < int_0)
			{
				long num3 = (long)BigNum.lessThan(mpi_1.plongArray_0.value_[i], num2);
				mpi_1.plongArray_0.value_[i] -= num2;
				if (mpi_1.plongArray_0.value_[i] < 0L)
				{
					mpi_1.plongArray_0.value_[i] += num;
				}
				num2 = (long)BigNum.lessThan(mpi_1.plongArray_0.value_[i], mpi_0.plongArray_0.value_[i]) + num3;
				mpi_1.plongArray_0.value_[i] -= mpi_0.plongArray_0.value_[i];
				if (mpi_1.plongArray_0.value_[i] < 0L)
				{
					mpi_1.plongArray_0.value_[i] += num;
				}
				i++;
			}
			while (num2 != 0L)
			{
				long num3 = (long)BigNum.lessThan(mpi_1.plongArray_0.value_[i], num2);
				mpi_1.plongArray_0.value_[i] -= num2;
				if (mpi_1.plongArray_0.value_[i] < 0L)
				{
					mpi_1.plongArray_0.value_[i] += num;
				}
				num2 = num3;
				i++;
			}
		}
		public static int mpiSubAbs(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			if (BigNum.mpiCmpAbs(mpi_1, mpi_2) < 0)
			{
				return -10;
			}
			int num;
			if (mpi_0 == mpi_2)
			{
				num = BigNum.mpiCopy(mPI, mpi_2);
				if (num != 0)
				{
					return num;
				}
				mpi_2 = mPI;
			}
			if (mpi_0 != mpi_1)
			{
				num = BigNum.mpiCopy(mpi_0, mpi_1);
				if (num != 0)
				{
					return num;
				}
			}
			num = 0;
			int num2 = mpi_2.int_1 - 1;
			while (num2 >= 0 && mpi_2.plongArray_0.value_[num2] == 0L)
			{
				num2--;
			}
			BigNum.mpiSubHlp(num2 + 1, mpi_2, mpi_0);
			return num;
		}
		public static int mpiAddMpi(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			int int_ = mpi_1.int_0;
			if (mpi_1.int_0 * mpi_2.int_0 < 0)
			{
				if (BigNum.mpiCmpAbs(mpi_1, mpi_2) >= 0)
				{
					int num = BigNum.mpiSubAbs(mpi_0, mpi_1, mpi_2);
					if (num != 0)
					{
						return num;
					}
					mpi_0.int_0 = int_;
				}
				else
				{
					int num = BigNum.mpiSubAbs(mpi_0, mpi_2, mpi_1);
					if (num != 0)
					{
						return num;
					}
					mpi_0.int_0 = -int_;
				}
			}
			else
			{
				int num = BigNum.mpiAddAbs(mpi_0, mpi_1, mpi_2);
				mpi_0.int_0 = int_;
			}
			return 0;
		}
		public static int mpiSubMpi(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			int int_ = mpi_1.int_0;
			if (mpi_1.int_0 * mpi_2.int_0 > 0)
			{
				if (BigNum.mpiCmpAbs(mpi_1, mpi_2) >= 0)
				{
					int num = BigNum.mpiSubAbs(mpi_0, mpi_1, mpi_2);
					if (num != 0)
					{
						return num;
					}
					mpi_0.int_0 = int_;
				}
				else
				{
					int num = BigNum.mpiSubAbs(mpi_0, mpi_2, mpi_1);
					if (num != 0)
					{
						return num;
					}
					mpi_0.int_0 = -int_;
				}
			}
			else
			{
				int num = BigNum.mpiAddAbs(mpi_0, mpi_1, mpi_2);
				mpi_0.int_0 = int_;
			}
			return 0;
		}
		public static int mpiAddInt(MPI mpi_0, MPI mpi_1, int int_0)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			mPI.plongArray_0.value_ = new long[1];
			if (int_0 < 0)
			{
				mPI.plongArray_0.value_[0] = (long)(-(long)int_0);
				mPI.int_0 = -1;
			}
			else
			{
				mPI.plongArray_0.value_[0] = (long)int_0;
				mPI.int_0 = 1;
			}
			mPI.int_1 = 1;
			return BigNum.mpiAddMpi(mpi_0, mpi_1, mPI);
		}
		public static int mpiSubInt(MPI mpi_0, MPI mpi_1, int int_0)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			mPI.plongArray_0.value_ = new long[1];
			if (int_0 < 0)
			{
				mPI.plongArray_0.value_[0] = (long)(-(long)int_0);
				mPI.int_0 = -1;
			}
			else
			{
				mPI.plongArray_0.value_[0] = (long)int_0;
				mPI.int_0 = 1;
			}
			mPI.int_1 = 1;
			return BigNum.mpiSubMpi(mpi_0, mpi_1, mPI);
		}
		public static void mpiMulHlp(int int_0, MPI mpi_0, MPI mpi_1, long long_0, int int_1)
		{
			long num = 0L;
			for (int i = 0; i < int_0; i++)
			{
				long num2 = mpi_0.plongArray_0.value_[i] * long_0 + num;
				num = num2 >> BigNum.biL;
				byte[] array = TypeTransform.longToByteArrayHL(num2);
				for (int j = 0; j <= 7 - BigNum.ciL; j++)
				{
					array[j] = 0;
				}
				mpi_1.plongArray_0.value_[int_1 + i] += TypeTransform.byteArrayHLToLong(array);
				long num3 = (long)BigNum.overflowAndModify(mpi_1, int_1 + i);
				int num4 = int_1 + i;
				while (num3 != 0L)
				{
					mpi_1.plongArray_0.value_[num4 + 1] += num3;
					num3 = (long)BigNum.overflowAndModify(mpi_1, num4 + 1);
					num4++;
				}
			}
		}
		public static int mpiMulMpi(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			MPI mPI = new MPI();
			MPI mPI2 = new MPI();
			BigNum.mpiInit(mPI);
			BigNum.mpiInit(mPI2);
			int num;
			if (mpi_0 == mpi_1)
			{
				num = BigNum.mpiCopy(mPI, mpi_1);
				if (num != 0)
				{
					return num;
				}
				mpi_1 = mPI;
			}
			if (mpi_0 == mpi_2)
			{
				num = BigNum.mpiCopy(mPI2, mpi_2);
				if (num != 0)
				{
					return num;
				}
				mpi_2 = mPI2;
			}
			int num2 = mpi_1.int_1 - 1;
			while (num2 >= 0 && mpi_1.plongArray_0.value_[num2] == 0L)
			{
				num2--;
			}
			int i = mpi_2.int_1 - 1;
			while (i >= 0 && mpi_2.plongArray_0.value_[i] == 0L)
			{
				i--;
			}
			num = BigNum.mpiGrow(mpi_0, num2 + i + 2);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiLset(mpi_0, 0);
			if (num != 0)
			{
				return num;
			}
			num2++;
			while (i >= 0)
			{
				BigNum.mpiMulHlp(num2, mpi_1, mpi_0, mpi_2.plongArray_0.value_[i], i);
				i--;
			}
			mpi_0.int_0 = mpi_1.int_0 * mpi_2.int_0;
			return 0;
		}
		public static int mpiMulInt(MPI mpi_0, MPI mpi_1, long long_0)
		{
			MPI mPI = new MPI();
			mPI.plongArray_0.value_ = new long[1];
			mPI.plongArray_0.value_[0] = long_0;
			mPI.int_0 = 1;
			mPI.int_1 = 1;
			return BigNum.mpiMulMpi(mpi_0, mpi_1, mPI);
		}
		public static int mpiDivMpi(MPI mpi_0, MPI mpi_1, MPI mpi_2, MPI mpi_3)
		{
			MPI mPI = new MPI();
			MPI mPI2 = new MPI();
			MPI mPI3 = new MPI();
			MPI mPI4 = new MPI();
			MPI mPI5 = new MPI();
			if (BigNum.mpiCmpInt(mpi_3, 0) == 0)
			{
				return -12;
			}
			BigNum.mpiInit(mPI);
			BigNum.mpiInit(mPI2);
			BigNum.mpiInit(mPI3);
			BigNum.mpiInit(mPI4);
			BigNum.mpiInit(mPI5);
			int num;
			if (BigNum.mpiCmpAbs(mpi_2, mpi_3) < 0)
			{
				if (mpi_0 != null)
				{
					num = BigNum.mpiLset(mpi_0, 0);
					if (num != 0)
					{
						return num;
					}
				}
				if (mpi_1 != null)
				{
					num = BigNum.mpiCopy(mpi_1, mpi_2);
					if (num != 0)
					{
						return num;
					}
				}
				return 0;
			}
			num = BigNum.mpiCopy(mPI, mpi_2);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiCopy(mPI2, mpi_3);
			if (num != 0)
			{
				return num;
			}
			MPI arg_A5_0 = mPI;
			mPI2.int_0 = 1;
			arg_A5_0.int_0 = 1;
			num = BigNum.mpiGrow(mPI3, mpi_2.int_1 + 2);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiLset(mPI3, 0);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiGrow(mPI4, 2);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiGrow(mPI5, 3);
			if (num != 0)
			{
				return num;
			}
			int i = BigNum.mpiMsb(mPI2) % BigNum.biL;
			if (i < BigNum.biL - 1)
			{
				i = BigNum.biL - 1 - i;
				num = BigNum.mpiShiftL(mPI, i);
				if (num != 0)
				{
					return num;
				}
				num = BigNum.mpiShiftL(mPI2, i);
				if (num != 0)
				{
					return num;
				}
			}
			else
			{
				i = 0;
			}
			int num2 = mPI.int_1 - 1;
			int num3 = mPI2.int_1 - 1;
			num = BigNum.mpiShiftL(mPI2, BigNum.biL * (num2 - num3));
			if (num != 0)
			{
				return num;
			}
			while (BigNum.mpiCmpMpi(mPI, mPI2) >= 0)
			{
				mPI3.plongArray_0.value_[num2 - num3] += 1L;
				BigNum.mpiSubMpi(mPI, mPI, mPI2);
			}
			BigNum.mpiShiftR(mPI2, BigNum.biL * (num2 - num3));
			BigInteger bigInteger_ = new BigInteger(Convert.ToString((int)mPI2.plongArray_0.value_[num3]));
			int j = num2;
			while (j > num3)
			{
				if (mPI.plongArray_0.value_[j] >= mPI2.plongArray_0.value_[num3])
				{
					byte[] array = new byte[8];
					for (i = 0; i < 8; i++)
					{
						if (i < 8 - BigNum.ciL)
						{
							array[i] = 0;
						}
						else
						{
							array[i] = (byte)SupportClass.Identity(255L);
						}
					}
					mPI3.plongArray_0.value_[j - num3 - 1] = TypeTransform.byteArrayHLToLong(array);
				}
				else
				{
					BigInteger bigInteger = new BigInteger(Convert.ToString((int)mPI.plongArray_0.value_[j]));
					BigInteger bigInteger2 = new BigInteger(Convert.ToString(1 << BigNum.biL));
					BigInteger bigInteger_2 = new BigInteger(Convert.ToString((int)mPI.plongArray_0.value_[j - 1]));
					BigInteger bigInteger3 = bigInteger.multiply(bigInteger2).vmethod_1(bigInteger_2).divide(bigInteger_);
					BigInteger bigInteger4 = bigInteger2.subtract(BigInteger.ONE);
					if (bigInteger3.compareTo(bigInteger4) >= 0)
					{
						bigInteger3 = bigInteger4;
					}
					byte[] array2 = bigInteger3.toByteArray();
					byte[] array3 = new byte[8];
					Arrays.fill(array3, 0);
					if (array2.Length >= 8)
					{
						Array.Copy(array2, array2.Length - 8, array3, 0, 8);
					}
					else
					{
						Array.Copy(array2, 0, array3, 8 - array2.Length, array2.Length);
					}
					mPI3.plongArray_0.value_[j - num3 - 1] = TypeTransform.byteArrayHLToLong(array3);
				}
				mPI3.plongArray_0.value_[j - num3 - 1] += 1L;
				do
				{
					mPI3.plongArray_0.value_[j - num3 - 1] -= 1L;
					num = BigNum.mpiLset(mPI4, 0);
					if (num != 0)
					{
						return num;
					}
					if (num3 < 1)
					{
						mPI4.plongArray_0.value_[0] = 0L;
					}
					else
					{
						mPI4.plongArray_0.value_[0] = mPI2.plongArray_0.value_[num3 - 1];
					}
					mPI4.plongArray_0.value_[1] = mPI2.plongArray_0.value_[num3];
					num = BigNum.mpiMulInt(mPI4, mPI4, mPI3.plongArray_0.value_[j - num3 - 1]);
					if (num != 0)
					{
						return num;
					}
					num = BigNum.mpiLset(mPI5, 0);
					if (num != 0)
					{
						return num;
					}
					if (j < 2)
					{
						mPI5.plongArray_0.value_[0] = 0L;
					}
					else
					{
						mPI5.plongArray_0.value_[0] = mPI.plongArray_0.value_[j - 2];
					}
					if (j < 1)
					{
						mPI5.plongArray_0.value_[1] = 0L;
					}
					else
					{
						mPI5.plongArray_0.value_[1] = mPI.plongArray_0.value_[j - 1];
					}
					mPI5.plongArray_0.value_[2] = mPI.plongArray_0.value_[j];
				}
				while (BigNum.mpiCmpMpi(mPI4, mPI5) > 0);
				num = BigNum.mpiMulInt(mPI4, mPI2, mPI3.plongArray_0.value_[j - num3 - 1]);
				if (num != 0)
				{
					return num;
				}
				num = BigNum.mpiShiftL(mPI4, BigNum.biL * (j - num3 - 1));
				if (num != 0)
				{
					return num;
				}
				num = BigNum.mpiSubMpi(mPI, mPI, mPI4);
				if (num == 0)
				{
					if (BigNum.mpiCmpInt(mPI, 0) < 0)
					{
						num = BigNum.mpiCopy(mPI4, mPI2);
						if (num != 0)
						{
							return num;
						}
						num = BigNum.mpiShiftL(mPI4, BigNum.biL * (j - num3 - 1));
						if (num != 0)
						{
							return num;
						}
						num = BigNum.mpiAddMpi(mPI, mPI, mPI4);
						if (num != 0)
						{
							return num;
						}
						mPI3.plongArray_0.value_[j - num3 - 1] -= 1L;
					}
					j--;
					continue;
				}
				return num;
			}
			if (mpi_0 != null)
			{
				BigNum.mpiCopy(mpi_0, mPI3);
				mpi_0.int_0 = mpi_2.int_0 * mpi_3.int_0;
			}
			if (mpi_1 != null)
			{
				BigNum.mpiShiftR(mPI, i);
				BigNum.mpiCopy(mpi_1, mPI);
				mpi_1.int_0 = mpi_2.int_0;
				if (BigNum.mpiCmpInt(mpi_1, 0) == 0)
				{
					mpi_1.int_0 = 1;
				}
			}
			return 0;
		}
		public static int mpiDivInt(MPI mpi_0, MPI mpi_1, MPI mpi_2, int int_0)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			mPI.plongArray_0.value_ = new long[1];
			if (int_0 < 0)
			{
				mPI.plongArray_0.value_[0] = (long)(-(long)int_0);
				mPI.int_0 = -1;
			}
			else
			{
				mPI.plongArray_0.value_[0] = (long)int_0;
				mPI.int_0 = 1;
			}
			mPI.int_1 = 1;
			return BigNum.mpiDivMpi(mpi_0, mpi_1, mpi_2, mPI);
		}
		public static int mpiModMpi(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			int num = BigNum.mpiDivMpi(null, mpi_0, mpi_1, mpi_2);
			if (num != 0)
			{
				return num;
			}
			while (BigNum.mpiCmpInt(mpi_0, 0) < 0)
			{
				num = BigNum.mpiAddMpi(mpi_0, mpi_0, mpi_2);
				if (num != 0)
				{
					return num;
				}
			}
			while (BigNum.mpiCmpMpi(mpi_0, mpi_2) >= 0)
			{
				num = BigNum.mpiSubMpi(mpi_0, mpi_0, mpi_2);
				if (num != 0)
				{
					return num;
				}
			}
			return 0;
		}
		public static int mpiModInt(PLong plong_0, MPI mpi_0, int int_0)
		{
			if (int_0 == 0)
			{
				return -12;
			}
			if (int_0 < 0)
			{
				int_0 = -int_0;
			}
			if (int_0 == 1)
			{
				plong_0.value_ = 0L;
				return 0;
			}
			if (int_0 == 2)
			{
				plong_0.value_ = (mpi_0.plongArray_0.value_[0] & 1L);
				return 0;
			}
			int i = mpi_0.int_1 - 1;
			long num = 0L;
			while (i >= 0)
			{
				long num2 = mpi_0.plongArray_0.value_[i];
				num = (num << BigNum.biH | num2 >> BigNum.biH);
				long num3 = num / (long)int_0;
				num -= num3 * (long)int_0;
				num2 <<= BigNum.biH;
				num = (num << BigNum.biH | num2 >> BigNum.biH);
				num3 = num / (long)int_0;
				num -= num3 * (long)int_0;
				i--;
			}
			plong_0.value_ = num;
			return 0;
		}
		public static void mpiMontgInit(PLong pL, MPI mpi_0)
		{
			long num = mpi_0.plongArray_0.value_[0];
			long num2 = num;
			num2 += (num + 2L & 4L) << 1;
			num2 *= 2L - num * num2;
			if (BigNum.biL >= 16)
			{
				num2 *= 2L - num * num2;
			}
			byte[] array = TypeTransform.longToByteArrayHL(~num2);
			for (int i = 0; i < 8 - BigNum.ciL; i++)
			{
				array[i] = 0;
			}
			pL.value_ = TypeTransform.byteArrayHLToLong(array) + 1L;
		}
		public static void mpiMontMul(MPI mpi_0, MPI mpi_1, MPI mpi_2, long long_0, MPI mpi_3)
		{
			mpi_3.plongArray_0.value_ = new long[mpi_3.int_1];
			Arrays.fill(mpi_3.plongArray_0.value_, 0);
			int int_ = mpi_2.int_1;
			int int_2;
			if (mpi_1.int_1 < int_)
			{
				int_2 = mpi_1.int_1;
			}
			else
			{
				int_2 = int_;
			}
			for (int i = 0; i < int_; i++)
			{
				long num = mpi_0.plongArray_0.value_[i];
				long long_ = (mpi_3.plongArray_0.value_[0] + num * mpi_1.plongArray_0.value_[0]) * long_0;
				BigNum.mpiMulHlp(int_2, mpi_1, mpi_3, num, i);
				BigNum.mpiMulHlp(int_, mpi_2, mpi_3, long_, i);
				mpi_3.plongArray_0.value_[i] = num;
				mpi_3.plongArray_0.value_[i + int_ + 1] = 0L;
			}
			Array.Copy(mpi_3.plongArray_0.value_, int_, mpi_0.plongArray_0.value_, 0, int_ + 1);
			if (BigNum.mpiCmpAbs(mpi_0, mpi_2) >= 0)
			{
				BigNum.mpiSubHlp(int_, mpi_2, mpi_0);
				return;
			}
			BigNum.mpiSubHlp(int_, mpi_0, mpi_3);
		}
		public static void mpiMontred(MPI mpi_0, MPI mpi_1, long long_0, MPI mpi_2)
		{
			MPI mPI = new MPI();
			BigNum.mpiInit(mPI);
			MPI arg_15_0 = mPI;
			mPI.int_0 = 1;
			arg_15_0.int_1 = 1;
			mPI.plongArray_0.value_ = new long[1];
			mPI.plongArray_0.value_[0] = 1L;
			BigNum.mpiMontMul(mpi_0, mPI, mpi_1, long_0, mpi_2);
		}
		public static int mpiExpMod(MPI mpi_0, MPI mpi_1, MPI mpi_2, MPI mpi_3, MPI _rr)
		{
			PLong pLong = new PLong();
			if (BigNum.mpiCmpInt(mpi_3, 0) >= 0)
			{
				if ((mpi_3.plongArray_0.value_[0] & 1L) != 0L)
				{
					MPI mPI = new MPI();
					BigNum.mpiInit(mPI);
					MPI mPI2 = new MPI();
					BigNum.mpiInit(mPI2);
					MPI[] array = new MPI[64];
					int i;
					for (i = 0; i < 64; i++)
					{
						array[i] = new MPI();
						BigNum.mpiInit(array[i]);
					}
					BigNum.mpiMontgInit(pLong, mpi_3);
					i = BigNum.mpiMsb(mpi_2);
					int num;
					if (i > 671)
					{
						num = 6;
					}
					else
					{
						if (i > 239)
						{
							num = 5;
						}
						else
						{
							if (i > 79)
							{
								num = 4;
							}
							else
							{
								if (i > 23)
								{
									num = 3;
								}
								else
								{
									num = 1;
								}
							}
						}
					}
					int num2 = mpi_3.int_1 + 1;
					int num3 = BigNum.mpiGrow(mpi_0, num2);
					if (num3 != 0)
					{
						return num3;
					}
					num3 = BigNum.mpiGrow(array[1], num2);
					if (num3 != 0)
					{
						return num3;
					}
					num3 = BigNum.mpiGrow(mPI2, num2 * 2);
					if (num3 != 0)
					{
						return num3;
					}
					if (_rr != null && _rr.plongArray_0.value_ != null)
					{
						BigNum.mpiCopy(mPI, _rr);
					}
					else
					{
						num3 = BigNum.mpiLset(mPI, 1);
						if (num3 != 0)
						{
							return num3;
						}
						num3 = BigNum.mpiShiftL(mPI, mpi_3.int_1 * 2 * BigNum.biL);
						if (num3 != 0)
						{
							return num3;
						}
						num3 = BigNum.mpiModMpi(mPI, mPI, mpi_3);
						if (num3 != 0)
						{
							return num3;
						}
						if (_rr != null)
						{
							BigNum.mpiCopy(_rr, mPI);
						}
					}
					if (BigNum.mpiCmpMpi(mpi_1, mpi_3) >= 0)
					{
						BigNum.mpiModMpi(array[1], mpi_1, mpi_3);
					}
					else
					{
						BigNum.mpiCopy(array[1], mpi_1);
					}
					BigNum.mpiMontMul(array[1], mPI, mpi_3, pLong.value_, mPI2);
					num3 = BigNum.mpiCopy(mpi_0, mPI);
					if (num3 != 0)
					{
						return num3;
					}
					BigNum.mpiMontred(mpi_0, mpi_3, pLong.value_, mPI2);
					if (num > 1)
					{
						num2 = 1 << num - 1;
						num3 = BigNum.mpiGrow(array[num2], mpi_3.int_1 + 1);
						if (num3 != 0)
						{
							return num3;
						}
						num3 = BigNum.mpiCopy(array[num2], array[1]);
						if (num3 != 0)
						{
							return num3;
						}
						for (i = 0; i < num - 1; i++)
						{
							BigNum.mpiMontMul(array[num2], array[num2], mpi_3, pLong.value_, mPI2);
						}
						for (i = num2 + 1; i < 1 << num; i++)
						{
							num3 = BigNum.mpiGrow(array[i], mpi_3.int_1 + 1);
							if (num3 != 0)
							{
								return num3;
							}
							num3 = BigNum.mpiCopy(array[i], array[i - 1]);
							if (num3 != 0)
							{
								return num3;
							}
							BigNum.mpiMontMul(array[i], array[1], mpi_3, pLong.value_, mPI2);
						}
					}
					int int_ = mpi_2.int_1;
					int num4 = 0;
					int num5 = 0;
					int num6 = 0;
					long num7 = 0L;
					while (true)
					{
						if (num4 == 0)
						{
							if (int_-- == 0)
							{
								break;
							}
							num4 = BigNum.ciL << 3;
						}
						num4--;
						long num8 = mpi_2.plongArray_0.value_[int_] >> num4 & 1L;
						if (num8 != 0L || num7 != 0L)
						{
							if (num8 == 0L && num7 == 1L)
							{
								BigNum.mpiMontMul(mpi_0, mpi_0, mpi_3, pLong.value_, mPI2);
							}
							else
							{
								num7 = 2L;
								num5++;
								num6 |= (int)((int)num8 << num - num5);
								if (num5 == num)
								{
									for (i = 0; i < num; i++)
									{
										BigNum.mpiMontMul(mpi_0, mpi_0, mpi_3, pLong.value_, mPI2);
									}
									BigNum.mpiMontMul(mpi_0, array[num6], mpi_3, pLong.value_, mPI2);
									num7 -= 1L;
									num5 = 0;
									num6 = 0;
								}
							}
						}
					}
					for (i = 0; i < num5; i++)
					{
						BigNum.mpiMontMul(mpi_0, mpi_0, mpi_3, pLong.value_, mPI2);
						num6 <<= 1;
						if ((num6 & 1 << num) != 0)
						{
							BigNum.mpiMontMul(mpi_0, array[1], mpi_3, pLong.value_, mPI2);
						}
					}
					BigNum.mpiMontred(mpi_0, mpi_3, pLong.value_, mPI2);
					return 0;
				}
			}
			return -4;
		}
		public static int mpiGcd(MPI mpi_0, MPI mpi_1, MPI mpi_2)
		{
			MPI mPI = new MPI();
			MPI mPI2 = new MPI();
			MPI mPI3 = new MPI();
			BigNum.mpiInit(mPI);
			BigNum.mpiInit(mPI2);
			BigNum.mpiInit(mPI3);
			int num = BigNum.mpiLset(mPI, 1);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiCopy(mPI2, mpi_1);
			if (num != 0)
			{
				return num;
			}
			num = BigNum.mpiCopy(mPI3, mpi_2);
			if (num != 0)
			{
				return num;
			}
			MPI arg_54_0 = mPI2;
			mPI3.int_0 = 1;
			arg_54_0.int_0 = 1;
			while (BigNum.mpiCmpInt(mPI2, 0) != 0)
			{
				while ((mPI2.plongArray_0.value_[0] & 1L) == 0L)
				{
					num = BigNum.mpiShiftR(mPI2, 1);
					if (num != 0)
					{
						return num;
					}
				}
				while ((mPI3.plongArray_0.value_[0] & 1L) == 0L)
				{
					num = BigNum.mpiShiftR(mPI3, 1);
					if (num != 0)
					{
						return num;
					}
				}
				if (BigNum.mpiCmpMpi(mPI2, mPI3) >= 0)
				{
					num = BigNum.mpiSubAbs(mPI2, mPI2, mPI3);
					if (num != 0)
					{
						return num;
					}
					num = BigNum.mpiShiftR(mPI2, 1);
					if (num != 0)
					{
						return num;
					}
				}
				else
				{
					num = BigNum.mpiSubAbs(mPI3, mPI3, mPI2);
					if (num != 0)
					{
						return num;
					}
					num = BigNum.mpiShiftR(mPI3, 1);
					if (num != 0)
					{
						return num;
					}
				}
			}
			num = BigNum.mpiMulMpi(mpi_0, mPI, mPI3);
			if (num != 0)
			{
				return num;
			}
			return 0;
		}
	}
}
